#pragma once

#include "module.hh"

#include <vector>
#include <memory>
#include <unordered_map>
#include <tuple>

template <typename KeyT, typename ValueT>
using Dict = std::unordered_map<KeyT, ValueT>;

struct ModuleInfo
{
    ModuleInfo(const String& line);

    char   type;
    String name;
    Vector<String> outputs;
};

class Network
{
public:
    Network(const String& filename);

public:
    auto print() -> void;

public:
    auto push_button() -> std::tuple<std::size_t, std::size_t>;

private:
    auto create_modules(const Vector<ModuleInfo> infos) -> void;
    auto connect_modules(const Vector<ModuleInfo> infos) -> void;

private:
    auto parse_name_and_kind(const String& line) -> std::tuple<String, ModuleKind>;
    auto parse_output_names(const String& line) -> Vector<String>;

    auto add_module(String name, ModuleKind kind) -> void;
    auto get_module(const String& name) -> Rc<Module>;

private:
    Vector<Rc<Module>>       _flips;
    Vector<Rc<Flipflop>>     _begins;
    Dict<String, Rc<Module>> _modules;
};